package org.rkuk.kasutil.uintTest.framework 
{
	import flash.events.EventDispatcher;
	import flash.utils.getQualifiedClassName;
	import org.rkuk.kasutil.uintTest.event.TestEvent;
	/**
	 * ...
	 * @author rkuk
	 */
	public class TestCase extends EventDispatcher
	{
		private var classToTest_:Class;
		private var objectToTest_:Object;
		private var setUpMethod_:TestMethod;
		private var tearDownMethod_:TestMethod;
		private var testMethod_:TestMethod;
		
		public function TestCase(classToTest:Class, testMethod:TestMethod, setUpMethod:TestMethod = null, tearDownMethod:TestMethod = null)
		{
			classToTest_ = classToTest;
			testMethod_ = testMethod;
			setUpMethod_ = setUpMethod || TestMethod.NULL_TEST_METHOD;
			tearDownMethod_ = tearDownMethod || TestMethod.NULL_TEST_METHOD;
		}
		
		public function run():void
		{
			startTest();
			
			runTestMethod(setUpMethod_, onSetUpEvent);
		}
		
		private function onSetUpEvent(e:TestEvent):void 
		{
			var method:TestMethod = e.target as TestMethod;
			method.removeEventListener(TestEvent.EXECUTE, onSetUpEvent);
			
			if (setUpMethod_.isSuccess)
				runTestMethod(testMethod_, onTestEvent);
			else
				endTest();
		}
		
		private function onTestEvent(e:TestEvent):void 
		{
			var method:TestMethod = e.target as TestMethod;
			method.removeEventListener(TestEvent.EXECUTE, onTestEvent);
			
			runTestMethod(tearDownMethod_, onTearDownEvent);
		}
		
		private function onTearDownEvent(e:TestEvent):void 
		{
			var method:TestMethod = e.target as TestMethod;
			method.removeEventListener(TestEvent.EXECUTE, onTearDownEvent);
			
			endTest();
		}
		
		private function runTestMethod(method:TestMethod,handler:Function):void 
		{
			if (method != null)
			{
				method.addEventListener(TestEvent.EXECUTE, handler);
				
				if (method.isStatic)
					method.execute(classToTest_);
				else
				{
					if (objectToTest_ == null)
						objectToTest_ = new classToTest_();
						
					method.execute(objectToTest_);
				}
			}
		}
		
		private function startTest():void 
		{
			TestEnviorenment.instance.startTest(classToTest_,testMethod_.methodName);
		}
		
		private function endTest():void 
		{
			TestEnviorenment.instance.endTest(classToTest_, testMethod_.methodName);
			notifyExecuted();
		}
		
		protected function notifyExecuted():void
		{
			dispatchEvent(new TestEvent(TestEvent.EXECUTE));
		}
	}

}